using IQIGame.Onigao.Framework;
using IQIGame.Onigao.Game;
using System;
using System.Collections.Generic;
using System.Text;
using UnityEngine;

namespace IQIGame.Onigao.GamePlay
{
    public class DevelopSettingModule : Singleton<DevelopSettingModule>
    {
        public enum DevelopSettingType
        {
            DebugWindow = 1,
            GmDebug = 2,
            Inspector = 3,
            UnityDebugLevel = 4,
            SkipFight = 5,
        }

        private DevelopSettingModule() { }

        #region Outside Develop
        private Dictionary<DevelopSettingType, bool> developData;
        private PlayerPreferenceString playerPrefsDevelopData { get; } = new PlayerPreferenceString(PlayerPrefsConst.DevelopSetting,string.Empty);

        #endregion
        private Dictionary<DevelopSettingType, bool> developDefaultData = new(2);

        public void Initialize()
        {
            InitializeData();
            OnInitialized();
        }

        private void InitializeData()
        {
            if (!string.IsNullOrEmpty(playerPrefsDevelopData.Value))
            {
                try
                {
                    developData = JsonHelper.DeserializeJson<Dictionary<DevelopSettingType, bool>>(playerPrefsDevelopData.Value);
                }
                catch (Exception ex)
                {
                    LogGame.LogException(ex);
                    developData = new(8);
                }
            }
            else
            {
                developData = new(8);
            }

            var cfgList = TableCenter.gmOutside.DataList;
            foreach (var cfg in cfgList)
            {
                DevelopSettingType developType = (DevelopSettingType)cfg.Type;
                if (!developData.TryGetValue(developType, out var develop))
                {
                    developDefaultData[developType] = cfg.Default && Debug.isDebugBuild;
                }
            }
        }
        
        private void OnInitialized()
        {
            var array = (DevelopSettingType[])Enum.GetValues(typeof(DevelopSettingType));
            foreach (var enumValue in array)
            {
                GetAction(enumValue)?.Invoke(GetIsOn(enumValue));
            }
        }

        public void Save(int type, bool isOn)
        {
            Save((DevelopSettingType)type, isOn);
        }

        public void Save(DevelopSettingType type, bool isOn)
        {
            bool isChanged = GetIsOn(type) != isOn;
            developData[type] = isOn;
            if (isChanged)
            {
                OnDataChanged(); 
                GetAction(type)?.Invoke(isOn);
            }
        }

        private void OnDataChanged()
        {
            playerPrefsDevelopData.Value = JsonHelper.SerializeObject(developData);
        }

        public bool GetIsOn(int type)
        {
            return GetIsOn((DevelopSettingType)type);
        }

        public bool GetIsOn(DevelopSettingType type)
        {
            if (developData.TryGetValue(type, out var value))
                return value;
            return developDefaultData.TryGetValue(type, out value) ? value : false;
        }

        #region Special 特殊需要处理的
        public Action<bool> GetAction(DevelopSettingType type)
        {
            return type switch
            {
                DevelopSettingType.DebugWindow => SetDebugWindow,
                DevelopSettingType.GmDebug => SetGmDebug,
                DevelopSettingType.Inspector => SetInspector,
                DevelopSettingType.UnityDebugLevel => SetUnityDebugLevel,
                _ => null,
            };
        }
        private void SetDebugWindow(bool isOn)
        {
            SetChildActive("Debuger", isOn);
            // 需要引用 Assembly
            // var element = UnityGameFramework.Runtime.DebuggerComponent.Instance;
            // if (element != null)
            // element.ActiveWindow = isOn;
        }

        private void SetChildActive(string childName, bool isOn)
        {
            // var root = GameObject.Find("/GameLaunch/FrameworkExt")?.transform;
            var root = GameObject.Find("/GameLaunch");
            if (root == null)
            {
                Debug.LogError("DevelopSettingModule is Not Find GameLaunch");
                return;
            }
            var mCenter = root.GetComponentInChildren<ManagerCenter>(true);
            if (mCenter == null)
            {
                Debug.LogError("DevelopSettingModule is Not Find ManagerCenter");
                return;
            }
            // if(Debug.isDebugBuild) 
            // Debug.LogError(GetHierarchyPath(mCenter.transform,"=== " ));
            var go = mCenter.transform.Find(childName)?.gameObject;
            go?.SetActive(isOn);
        }

        private string GetHierarchyPath(Transform transform, string head)
        {
            if (transform == null)
                return head;
            var parents = transform.GetComponentsInParent<Transform>(true);
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.Append(head);
            foreach (var parent in parents)
            {
                stringBuilder.Append("/").Append(parent.name);
            }
            string result = stringBuilder.ToString();
            stringBuilder.Clear();
            return result;
        }

        private void SetGmDebug(bool isOn)
        {
            SetChildActive("GM", isOn);
        }

        private void SetInspector(bool isOn)
        {
            SetChildActive("InspectorCanvas", isOn);
        }

        private void SetUnityDebugLevel(bool isOn)
        {
            LogType logType = isOn ? LogType.Error : LogType.Log;
            Debug.unityLogger.filterLogType = logType;
        }
        #endregion
    }
}
